package org.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.dao.UserDao;
import org.example.entity.ClanDetail;
import org.example.entity.FamilyDetail;
import org.example.entity.User;
import org.example.exception.AccountExitException;
import org.example.exception.AccountNotExitException;
import org.example.exception.PermissionsDenyException;
import org.example.service.ClanDetailService;
import org.example.service.FamilyDetailService;
import org.example.service.RedisService;
import org.example.service.UserService;
import org.example.utils.PhoneUtils;
import org.example.utils.TimeUtils;
import org.example.vo.RegisterVo;
import org.example.utils.PasswordUtils;
import org.example.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

import static org.example.interceptor.LoginInterceptor.threadLocal;
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    @Autowired
    UserService userService;
    @Autowired
    ClanDetailService clanDetailService;
    @Autowired
    FamilyDetailService familyDetailService;
    @Autowired
    RedisService redisService;
    @Override
    public User getUserByAccount(String account) {
        return userService.getOne(new QueryWrapper<User>().eq("account",account));
    }

    @Override
    public void createUser(RegisterVo registerVo, int i) throws AccountExitException {
        User user = getUserByAccount(registerVo.account);
        if(user==null){
            user = new User(registerVo,0);
            userService.changePasswordAndSave(user);

        }else
            throw new AccountExitException();
    }

    @Override
    public void changePasswordAndSave(User user) {
        user.password = PasswordUtils.MD5Encode(user.password);
        userService.saveOrUpdate(user);
    }

    /***
     *
     * @param user
     * @param target 这里的target都是聪数据库中取出来的，保真
     * @return
     */
    public boolean isParent(User user ,User target){
        //对方不是小孩 一定不是他家长
        if(target.isChild==0) return false;
        FamilyDetail familyDetail = familyDetailService.getOne(new QueryWrapper<FamilyDetail>().eq("user_id", user.id).eq("exits",1));
        //自己不是家长 一定不是他家长
        if(familyDetail.role==0) return false;

        familyDetail = familyDetailService.getOne(
                new QueryWrapper<FamilyDetail>().
                        eq("user_id",target.id)
                        .eq("family_id",familyDetail.getFamilyId())
                        .eq("exits",1));
        if(familyDetail==null) return false;
        return true;
    }
    public int getParentId(User user){
        if(user.isChild==0) return user.id;
        else{
            FamilyDetail familyDetail = familyDetailService.getOne(new QueryWrapper<FamilyDetail>().eq("exits", 1)
                    .eq("user_id", user.id));
            int familyId = familyDetail.getFamilyId();
            FamilyDetail familyDetail1 = familyDetailService.getOne(new QueryWrapper<FamilyDetail>()
                    .eq("exits",1).eq("family_id",familyId)
                    .eq("role",1));
            return  familyDetail1.getUserId();
        }//那个家庭的家长
    }
    public boolean isManager(User user,User target){
        ClanDetail clanDetail = clanDetailService.getOne(new QueryWrapper<ClanDetail>().eq("user_id",user.id)
                .eq("exits",1).eq("role",1));
        if(clanDetail==null) return false;
        //只要有权管家长就可以了
        ClanDetail cd = clanDetailService.getOne(new QueryWrapper<ClanDetail>().eq("user_id", getParentId(target))
                .eq("clan_id", clanDetail.getClanId()).eq("exits",1));
        if(cd==null) return false;
        return true;
    }
    @Transactional
    @Override
    public UserVO updateUser(User target) throws AccountNotExitException, PermissionsDenyException {
        User user = threadLocal.get();
        //用户已经失效了
        User curUser = userService.getById(target.id);
        if(curUser.exits==0) throw new AccountNotExitException();
        //用户鉴权
        if(!isManager(user,curUser)) throw new PermissionsDenyException();


        User changedUser = userInfo(target,curUser);
        userService.saveOrUpdate(changedUser);
        //级联修改
        if(target.name!=null){
            Date currentTime = TimeUtils.getCurrentTime();
            List<ClanDetail> clanDetails = clanDetailService.list(new QueryWrapper<ClanDetail>().eq("user_id", changedUser.id));
            for (int i = 0; i < clanDetails.size(); i++){
                clanDetails.get(i).setName(changedUser.name);
                clanDetails.get(i).setUpdateTime(currentTime);
            }
            clanDetailService.saveOrUpdateBatch(clanDetails);
            List<FamilyDetail> familyDetails = familyDetailService.list(new QueryWrapper<FamilyDetail>().eq("user_id",changedUser.id));
            for (int i = 0; i < familyDetails.size(); i++){
                familyDetails.get(i).setName(changedUser.name);
                familyDetails.get(i).setUpdateTime(currentTime);
            }
            familyDetailService.saveOrUpdateBatch(familyDetails);
        }
        //token失效
        if(target.password!=null){
            redisService.deleteToken(target.id);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(changedUser,new UserVO());
        return userVO;
    }

    public User userInfo(User target,User curUser)  {
        if(target.name!=null) curUser.name=target.name;
        if(target.password!=null) curUser.password=PasswordUtils.MD5Encode(target.password);
        if(target.phone!=null){
            if(PhoneUtils.isMobileNO(target.phone)){
                curUser.phone=PhoneUtils.encode(target.phone);
            }
        }
        if(target.grade!=null) curUser.grade=target.grade;
        if(target.gender!=null) curUser.gender=target.gender;
        if(target.birthday!=null) curUser.birthday =target.birthday;
        curUser.updateTime = TimeUtils.getCurrentTime();
        return curUser;
    }
}
